import java.util.*;
public class Operation {
    //JZ65 不用加减乘除做加法
    public int Add(int num1,int num2) {
        //进位
        int add = num1;
        //本位
        int sum = num2;
        while(add != 0){
            //保留本位
            int tmp = add ^ sum;
            //产生进位
            add = (sum & add) << 1;
            //更新sum
            sum = tmp;
        }
        return sum;
    }
    //JZ65 不用加减乘除做加法(优化相同情况)
    public int Add(int num1,int num2) {
        //优化两数相同情况
        if(num1 == num2){
            return num1 << 1;
        }
        //进位
        int add = num1;
        //本位

        int sum = num2;
        while(add != 0){
            //保留本位
            int tmp = add ^ sum;
            //产生进位
            add = (sum & add) << 1;
            //更新sum
            sum = tmp;
        }
        return sum;
    }
    //JZ15 二进制中1的个数
    public int NumberOf1(int n) {
        int count = 0;
        while(n != 0){
            if((n & 1) == 1){
                count++;
            }
            //小心负数情况
            n >>>= 1;
        }
        return count;
    }
    //JZ16 数值的整数次方
    public double Power(double base, int exponent) {
        double ret = base;
        if(exponent > 0){
            //累乘
            for(int i = 1; i < exponent; i++){
                ret *= base;
            }
        }else{
            ret = 1;
            for(int i = 0; i < -exponent; i++){
                ret /= base;
            }
        }
        return ret;
    }
    //JZ56 数组中只出现一次的两个数字
    public int[] FindNumsAppearOnce (int[] array) {
        int[] retArr = new int[2];
        HashMap<Integer, Integer> map = new HashMap<>();
        int len = array.length;
        //统计出现数量
        for(int i = 0; i < len; i++) {
            //若出现过，就用2来代替多次情况，时间上得以优化
            if(map.containsKey(array[i])){
                map.put(array[i], 2);
            }else{
                map.put(array[i], 1);
            }
        }
        //retArr的下标
        int count = 0;
        for(int i = 0; i < len; i++){
            if(map.get(array[i]) == 1){
                retArr[count++] = array[i];
            }
        }
        if(retArr[0] > retArr[1]){
            swap(retArr, 0, 1);
        }
        return retArr;
    }
    private void swap(int[] array, int i, int j){
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
    //JZ64 求1+2+3+...+n
    public int Sum_Solution(int n) {
        //利用短路思维，代替if语句，利用递归代替循环
        boolean flag = (n > 0) && ((n += Sum_Solution(n - 1)) > 0);
        return n;
    }
    //JZ29 顺时针打印矩阵
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> array = new ArrayList<>();
        //先排除为空的情况
        if(matrix.length == 0){
            return array;
        }
        //模拟边界
        //行列长度
        int line = matrix[0].length;
        int row = matrix.length;
        //左边界
        int left = 0;
        //右边界
        int right = line - 1;
        //上边界
        int up = 0;
        //下边界
        int down = row - 1;
        while(left <= right && up <= down){
            //先将上边界从左往右放入
            for(int i = left; i <= right; i++){
                //上边界来作为当前行
                array.add(matrix[up][i]);
            }
            //控制大小
            if(line * row == array.size()){
                break;
            }
            //将右边界值由上到下放入(上边界第一层放过了，跳过即可)
            for(int i = up + 1; i <= down; i++){
                //右边界来作为当前列
                array.add(matrix[i][right]);
            }

            //将下边界从右往左放入(有边界第一列放过，跳过即可)
            for(int i = right - 1; i >= left; i--){
                //下边界来作为当前行
                array.add(matrix[down][i]);
            }
            //控制大小
            if(line * row == array.size()){
                break;
            }
            //将左边界从下往上放入(下边界放过，跳过即可，注意:顶部已经放过，不变再放)
            for(int i = down - 1; i > up; i--){
                //左边界作为当前列
                array.add(matrix[i][left]);
            }
            //调整边界
            up++;
            right--;
            down--;
            left++;
        }
        return array;
    }
}
